import React, { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useState } from "react";
import PropTypes from "prop-types";
import lodash from "lodash";
import { CONST_VIEWSTOREACTION_INIT, CONST_VIEWSTORECOMBINEREDUCERFLAGB, CONST_VIEWSTOREREDUCERFLAG } from "../data";
import { useStore } from "./useStore";

interface IStoreProviderProps {
    name: string;
    reducers: Record<string,{ initState: any, handler: Function}>| Function;
    //当reducers为Function时需要传此参数
    initState?: any;
    children?: any;
}

export const StoreContext = React.createContext<any>({});

const StoreProvider = ({ reducers, children, name, initState }: IStoreProviderProps) => {
    const store = useStore();
    
    const [ tmpState ] = useState({
        isRegisted: false
    });
    const reducerHandlers = useMemo(() => {
        const handlers = [];
        if(typeof reducers === "function") {
            handlers.push({
                name,
                action: reducers,
                initState
            });
        } else {
            Object.keys(reducers).forEach((actionName: string) => {
                handlers.push({
                    name: `${name}.${actionName}`,
                    action: reducers[actionName].handler,
                    initState: reducers[actionName].initState
                });
            });
        }
        return handlers;
    }, [name, reducers]);
    const initStateData = useMemo(() => {
        const tempState = {};
        if(!tmpState.isRegisted){
            tmpState.isRegisted = true;
            reducerHandlers.forEach((item) => {
                const itemInitState = store.registeState(item.name, item.action, item.initState);
                lodash.merge(tempState, {[item.name]: itemInitState});
            })
        }
        return tmpState;
    }, [reducerHandlers]);
    const stateContext = useMemo(() => ({
        initState: initStateData
    }), [initStateData]);
    useEffect(() => {
        store.initState();
        return () => {
            reducerHandlers.forEach((item) => {
                store.unRegisteState(item.name);
            })
        }
    }, []);
    return (<StoreContext.Provider value={stateContext}>
        {children}
    </StoreContext.Provider>);
};
StoreProvider.propTypes = {
    name: PropTypes.string.isRequired
};
export const createProvider = <IState extends {}>(
    initState: IState,
    reducerHandler: Function,
    name?: string
    ) => (props: { name: string }) => {
        return <StoreProvider {...props} initState={initState} name={name || props.name} reducers={reducerHandler} />
    };

export const createCombineProvider = (
    parentReducer: AppViewStore.ICreateReducer<any>,
    configReducers: Record<string, AppViewStore.ICreateReducer<any>>
) => {
    const ParentStateProvider = parentReducer.StateProvider;
    const Provider = (props: any) => {
        const store = useStore();
        const bindName = props.name;
        useLayoutEffect(() => {
            for(const itemKey of Object.keys(configReducers)) {
                const detectItem = configReducers[itemKey];
                const reducerStateKey = `${bindName}.${itemKey}`;
                if(![CONST_VIEWSTOREREDUCERFLAG, CONST_VIEWSTORECOMBINEREDUCERFLAGB].includes(detectItem.flag as any)) {
                    throw new Error(`混合State必须使用createReducer方法创建。(${itemKey})`);
                }
                (detectItem as any).setName(reducerStateKey);
                store.registeState(reducerStateKey, detectItem.handler,detectItem.state);
            }
        }, []);
        useEffect(() => () => {
            for(const itemKey of Object.keys(configReducers)) {
                const reducerStateKey = `${bindName}.${itemKey}`;
                store.unRegisteState(reducerStateKey);
            }
        },[]);
        return (<>{props.children}</>);
    };
    const bindName = parentReducer.name;
    for(const itemKey of Object.keys(configReducers)) {
        const detectItem = configReducers[itemKey];
        const reducerStateKey = `${bindName}.${itemKey}`;
        if(![CONST_VIEWSTOREREDUCERFLAG, CONST_VIEWSTORECOMBINEREDUCERFLAGB].includes(detectItem.flag as any)) {
            throw new Error(`混合State必须使用createReducer方法创建。(${itemKey})`);
        }
        (detectItem as any).setName(reducerStateKey);
    }
    return {
        Provider: (props: any) => {
            return <ParentStateProvider>
                <Provider {...props} name={parentReducer.name || props.name}/>
            </ParentStateProvider>;
        },
        useViewState: () => {
            console.log("-----Application---");
        }
    };
};